home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Text / Edit / GoldED-Demo / installdata / golded / developer / api / examples / button / funcs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  11.3 KB  |  428 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.  button.api ©1999 Dietmar Eilert
  4.  
  5.  Plug-in example. This plug-in opens a container and shows a gadget.
  6.  
  7.  DMAKE
  8.  
  9.  -------------------------------------------------------------------------------
  10.  
  11. */
  12.  
  13. #include "defs.h"
  14.  
  15. /// "prototypes"
  16.  
  17. // library functions
  18.  
  19. Prototype LibCall struct APIClient *APIMountClient(__A0 struct APIMessage *, __A1 char *);
  20. Prototype LibCall void              APICloseClient(__A0 struct APIClient  *, __A1 struct APIMessage *);
  21. Prototype LibCall void              APIBriefClient(__A0 struct APIClient  *, __A1 struct APIMessage *);
  22. Prototype LibCall void              APIFree       (__A0 struct APIClient  *, __A1 struct APIOrder   *);
  23.  
  24. // private functions
  25.  
  26. Prototype ULONG DispatchContainer(struct APIClient     *, struct APIMessage *);
  27. Prototype ULONG AttachGadgets    (struct PlugInContext *, struct APIMessage *);
  28. Prototype ULONG DetachGadgets    (struct PlugInContext *, struct APIMessage *);
  29.  
  30. ///
  31. /// "defines"
  32.  
  33. // we allocate a context structure for each instance of this client to store local data
  34.  
  35. struct PlugInContext {
  36.  
  37.     struct APIClient        APIClient;               // API handle (exposed to host)
  38.     struct Gadget          *Context;                 // private data: gadget list
  39.     UWORD                   Gadgets;                 // private data: gadget counter
  40. };
  41.  
  42. ///
  43. /// "library functions"
  44.  
  45. LibCall struct APIClient *
  46. APIMountClient(__A0 struct APIMessage *apiMsg, __A1 char *args)
  47. {
  48.     struct PlugInContext *context;
  49.  
  50.     // build a description of this client (host will pass this back to us as "handle" during subsequent library calls)
  51.  
  52.     if (context = (struct PlugInContext *)AllocVec(sizeof(struct PlugInContext), MEMF_ANY | MEMF_CLEAR)) {
  53.  
  54.         if (context->APIClient.api_Area = (struct APIArea *)AllocVec(sizeof(struct APIArea), MEMF_ANY | MEMF_CLEAR)) {
  55.  
  56.             // client description
  57.  
  58.             context->APIClient.api_APIVersion = API_INTERFACE_VERSION;
  59.             context->APIClient.api_Version    = 1;
  60.             context->APIClient.api_Name       = "Button";
  61.             context->APIClient.api_Info       = "Plug-in example";
  62.             context->APIClient.api_Commands   = NULL;
  63.             context->APIClient.api_Serial     = 0;
  64.             context->APIClient.api_Classes    = API_CLASS_SYSTEM | API_CLASS_CONTAINER;
  65.  
  66.             // prepare the container request
  67.  
  68.             context->APIClient.api_Area->api_Width     = 20;
  69.             context->APIClient.api_Area->api_Height    = 5;
  70.             context->APIClient.api_Area->api_UnitsX    = API_UNITS_FONT;
  71.             context->APIClient.api_Area->api_UnitsY    = API_UNITS_FONT;
  72.             context->APIClient.api_Area->api_Alignment = API_ALIGN_RIGHT;
  73.             context->APIClient.api_Area->api_Style     = API_STYLE_STANDARD;
  74.             context->APIClient.api_Area->api_IDCMP     = IDCMP_GADGETUP;
  75.         }
  76.         else {
  77.  
  78.             FreeVec(context);
  79.  
  80.             context = NULL;
  81.         }
  82.     }
  83.  
  84.     return((struct APIClient *)context);
  85. }
  86.  
  87. LibCall void
  88. APICloseClient(__A0 struct APIClient *handle, __A1 struct APIMessage *apiMsg)
  89. {
  90.     // free ressources related to this client
  91.  
  92.     FreeVec(handle->api_Area);
  93.  
  94.     FreeVec(handle);
  95. }
  96.  
  97. LibCall void
  98. APIBriefClient(__A0 struct APIClient *handle, __A1 struct APIMessage *apiMsg)
  99. {
  100.     struct APIMessage *msg;
  101.  
  102.     // handle host's command notify
  103.  
  104.     for (msg = apiMsg; msg; msg = msg->api_Next) {
  105.  
  106.         if (msg->api_State == API_STATE_NOTIFY) {
  107.  
  108.             switch (msg->api_Class) {
  109.  
  110.                 case API_CLASS_CONTAINER:
  111.  
  112.                     msg->api_Error = DispatchContainer(handle, msg);
  113.  
  114.                     break;
  115.  
  116.                 case API_CLASS_SYSTEM:
  117.  
  118.                     msg->api_Error = API_ERROR_OK;
  119.  
  120.                     break;
  121.  
  122.                 default:
  123.  
  124.                     msg->api_Error = API_ERROR_UNKNOWN;
  125.             }
  126.         }
  127.     }
  128. }
  129.  
  130.  
  131. LibCall void
  132. APIFree(__A0 struct APIClient *handle, __A1 struct APIOrder *apiOrder)
  133. {
  134.     struct APIOrder *order, *next;
  135.  
  136.     // free data allocated for orders sent to host
  137.  
  138.     for (order = apiOrder; order; order = next) {
  139.  
  140.         next = order->api_Next;
  141.  
  142.         switch (order->api_Flags) {
  143.  
  144.             case API_ORDER_DETACH:
  145.  
  146.                 FreeGadgets((struct Gadget *)order->api_Data);
  147.  
  148.                 break;
  149.         }
  150.  
  151.         FreeVec(order);
  152.     }
  153. }
  154.  
  155. ///
  156. /// "private functions"
  157.  
  158. /* ----------------------------- DispatchContainer -----------------------------
  159.  
  160.  Handle container-related event
  161.  
  162. */
  163.  
  164. ULONG
  165. DispatchContainer(handle, apiMsg)
  166.  
  167. struct APIClient  *handle;
  168. struct APIMessage *apiMsg;
  169. {
  170.     ULONG error = API_ERROR_OK;
  171.  
  172.     switch (apiMsg->api_Action) {
  173.  
  174.         case API_ACTION_DETACH:
  175.  
  176.             // request to detach gadgets from window
  177.  
  178.             error = DetachGadgets((struct PlugInContext *)handle, apiMsg);
  179.  
  180.             break;
  181.  
  182.         case API_ACTION_ATTACH:
  183.  
  184.             // request to attach gadgets
  185.  
  186.             error = AttachGadgets((struct PlugInContext *)handle, apiMsg);
  187.  
  188.             break;
  189.  
  190.         case API_ACTION_PAINT:
  191.  
  192.             // paint user interface
  193.  
  194.             {
  195.                 struct PlugInContext *context = (struct PlugInContext *)handle;
  196.  
  197.                 if (context->Context)
  198.  
  199.                     RefreshGList(context->Context, apiMsg->api_Instance->api_Window, NULL, context->Gadgets);
  200.             }
  201.  
  202.             break;
  203.  
  204.         case API_ACTION_REFRESH:
  205.  
  206.             // refresh the user interface (nothing to do here: gadgets are refreshed automatically)
  207.  
  208.             break;
  209.  
  210.         case API_ACTION_INPUTEVENT:
  211.  
  212.             // input event to be handled
  213.  
  214.             struct APIInputEvent *event;
  215.  
  216.             if (event = (struct APIInputEvent *)apiMsg->api_Data) {
  217.  
  218.                 switch (event->api_IDCMPClass) {
  219.  
  220.                     case IDCMP_GADGETUP:
  221.  
  222.                         {
  223.                             // is this event meant for our window ?
  224.  
  225.                             if (event->api_IDCMPWindow == apiMsg->api_Instance->api_Window) {
  226.  
  227.                                 struct Gadget *gadget = (struct Gadget *)event->api_IDCMPAddress;
  228.  
  229.                                 // one of our gadgets ?
  230.  
  231.                                 if (gadget->GadgetID == apiMsg->api_Instance->api_Container->api_Namespace) {
  232.  
  233.                                     apiMsg->api_Status = "Gadget event detected by plug-in !";
  234.  
  235.                                     // no further processing of this input event required
  236.  
  237.                                     apiMsg->api_State = API_STATE_CONSUMED;
  238.                                 }
  239.                             }
  240.                         }
  241.  
  242.                         break;
  243.                 }
  244.             }
  245.  
  246.             break;
  247.  
  248.         default:
  249.  
  250.             error = API_ERROR_UNKNOWN;
  251.     }
  252.  
  253.     return(error);
  254. }
  255.  
  256.  
  257. /* ------------------------------- DetachGadgets -------------------------------
  258.  
  259.  Detach gadgets from window
  260.  
  261. */
  262.  
  263. ULONG
  264. DetachGadgets(context, apiMsg)
  265.  
  266. struct PlugInContext *context;
  267. struct APIMessage    *apiMsg;
  268. {
  269.     // any gadgets attached to window ?
  270.  
  271.     if (context->Context) {
  272.  
  273.         // prepare order to send a command ("detach these gadgets from the window") to the host
  274.  
  275.         if (apiMsg->api_Order = (struct APIOrder *)AllocVec(sizeof(struct APIOrder), MEMF_PUBLIC | MEMF_CLEAR)) {
  276.  
  277.             // create order for host to have gadgets detached
  278.  
  279.             apiMsg->api_Order->api_Flags = API_ORDER_DETACH;
  280.  
  281.             apiMsg->api_Order->api_Data = context->Context;
  282.  
  283.             // gadgets now assumed to be detached from window
  284.  
  285.             context->Context = NULL;
  286.  
  287.             // see APIFree() function for further processing (disposal of gadget list)
  288.         }
  289.     }
  290.  
  291.     return(API_ERROR_OK);
  292. }
  293.  
  294.  
  295. /* ------------------------------- AttachGadgets -------------------------------
  296.  
  297.  Attach gadgets to window
  298.  
  299. */
  300.  
  301. ULONG
  302. AttachGadgets(context, apiMsg)
  303.  
  304. struct PlugInContext *context;
  305. struct APIMessage    *apiMsg;
  306. {
  307.     ULONG error;
  308.  
  309.     // already attached to window ?
  310.  
  311.     if (context->Context) {
  312.  
  313.         error = API_ERROR_OK;
  314.     }
  315.     else {
  316.  
  317.         struct APIContainer *container;
  318.  
  319.         error = API_ERROR_FAIL;
  320.  
  321.         if (container = apiMsg->api_Instance->api_Container) {
  322.  
  323.             // container not fully obscured ?
  324.  
  325.             if (container->api_Clipping) {
  326.  
  327.                 UWORD x0;
  328.                 UWORD y0;
  329.                 UWORD x1;
  330.                 UWORD y1;
  331.                 UWORD w;
  332.                 UWORD h;
  333.  
  334.                 // determine space available for gadgets
  335.  
  336.                 x0 = container->api_Clipping->MinX;
  337.                 y0 = container->api_Clipping->MinY;
  338.                 x1 = container->api_Clipping->MaxX;
  339.                 y1 = container->api_Clipping->MaxY;
  340.  
  341.                 // center gadget in container
  342.  
  343.                 w   = (x1 - x0 + 1) / 2;
  344.                 h   = (y1 - y0 + 1) / 2;
  345.  
  346.                 x0 += (w / 2);
  347.                 y0 += (h / 2);
  348.  
  349.                 if ((w >= 2) && (h >= 2)) {
  350.  
  351.                     struct Gadget *gadget;
  352.                     UBYTE         *label;
  353.                     UWORD          labelsize;
  354.  
  355.                     label = "button";
  356.  
  357.                     // does label fit into gadget ?
  358.  
  359.                     labelsize = TextLength(container->api_RPort, label, strlen(label));
  360.  
  361.                     if (container->api_TextAttr->ta_YSize > h) {
  362.  
  363.                         label = NULL;
  364.                     }
  365.                     else if (labelsize > w)
  366.  
  367.                         label = NULL;
  368.  
  369.                     // create the gadget
  370.  
  371.                     if (gadget = CreateContext(&context->Context)) {
  372.  
  373.                         static struct TagItem tags[] = { GT_Underscore, '_', TAG_DONE };
  374.  
  375.                         struct NewGadget ng;
  376.  
  377.                         ng.ng_GadgetText = label;
  378.                         ng.ng_LeftEdge   = x0;
  379.                         ng.ng_TopEdge    = y0;
  380.                         ng.ng_Width      = w;
  381.                         ng.ng_Height     = h;
  382.                         ng.ng_VisualInfo = container->api_VisualInfo;
  383.                         ng.ng_GadgetID   = container->api_Namespace;
  384.                         ng.ng_TextAttr   = container->api_TextAttr;
  385.                         ng.ng_Flags      = PLACETEXT_IN;
  386.                         ng.ng_UserData   = context;
  387.  
  388.                         if (gadget = CreateGadgetA(BUTTON_KIND, gadget, &ng, tags)) {
  389.  
  390.                             // count gadgets (result may differ from the logical gadget count for some gadtools types)
  391.  
  392.                             context->Gadgets = 0;
  393.  
  394.                             for (gadget = context->Context; gadget; gadget = gadget->NextGadget)
  395.  
  396.                                 ++context->Gadgets;
  397.  
  398.                             // create order for host to have gadgets added to the window
  399.  
  400.                             if (apiMsg->api_Order = (struct APIOrder *)AllocVec(sizeof(struct APIOrder), MEMF_PUBLIC | MEMF_CLEAR)) {
  401.  
  402.                                 apiMsg->api_Order->api_Flags = API_ORDER_ATTACH;
  403.  
  404.                                 apiMsg->api_Order->api_Data = context->Context;
  405.  
  406.                                 // set return code
  407.  
  408.                                 error = API_ERROR_OK;
  409.                             }
  410.                             else {
  411.  
  412.                                 FreeGadgets(context->Context);
  413.  
  414.                                 context->Context = NULL;
  415.                                 context->Gadgets = 0;
  416.                             }
  417.                         }
  418.                     }
  419.                 }
  420.             }
  421.         }
  422.     }
  423.  
  424.     return(error);
  425. }
  426.  
  427. ///
  428.